package com.example.demo2_review.changYongJiHe;

import java.util.*;

/**
 * @Author zwp14
 * @create 2024/6/7 17:26
 * @description 集合方法
 */
public class Demo2Collection {
    public static void main(String[] args) {
        //List：ArrayList，LinkedList
        arrayListAndLinkedList();
        //Set：HashSet，TreeSet
        hashSetAndTreeSetAndLinkedHashSet();
        //Queue：ArrayQueue，PriorityQueue
        arrayQueueAndPriorityQueue();
    }

    /**
     * 队列Queue
     */
    private static void arrayQueueAndPriorityQueue() {
        /*
        1-ArrayDeque
        适用场景：
            高效的头部和尾部操作，需要一个既可以作为队列又可以作为栈使用的数据结构
        特性：
            内部使用数组实现，可以进行动态扩展
            支持高效的插入和删除操作，时间复杂度o(1)
            不支持在队列中间进行插入和删除操作，这样会导致数据移动，大量索引变更
         */
        Queue<Integer> arrayQueue = new ArrayDeque<>();
        arrayQueue.add(1);
        arrayQueue.add(3);
        arrayQueue.add(2);
        System.out.println("Queue-arrayQueue:"+arrayQueue);
        Deque<Integer> arrayDeque = new ArrayDeque<>();
        arrayDeque.add(1);
        arrayDeque.addFirst(3);
        arrayDeque.addLast(2); //输出结果：[3, 1, 2]

        /*
        进行完首尾操作后再进行add操作，默认在末尾进行元素添加
        arrayDeque.addFirst(3);
        arrayDeque.addLast(2);
        arrayDeque.add(1); 输出结果：[3, 2, 1]
        */
        System.out.println("Deque-arrayDeque"+arrayDeque);


        /*
        2-PriorityQueue
        适用场景：
            需要根据元素的优先级来获取和处理元素时
            当你希望按照某种顺序!处理!队列中的元素时，而不是简单的先入先出
        特性：
            ！！内部使用堆（最小堆或最大堆）实现，可以用于实现优先级排序！！
            在迭代和直接打印时，并不保证按照优先级顺序输出元素，因为它是基于堆实现的
            如果需要按照自定义的优先级顺序输出元素，建议使用 poll() 方法逐个取出，或者将元素复制到列表中进行排序输出。
            实现了优先级队列的功能，其中元素按照自然顺序或者通过提供的 Comparator 进行排序。
            插入操作的时间复杂度为 O(log n)，获取优先级最高元素的时间复杂度为 O(1)。
         */
//        Queue<Integer> pq = new PriorityQueue<>((a, b) -> Integer.compare(Math.abs(a), Math.abs(b))); //比较器compare
        Queue<Integer> pq = new PriorityQueue<>();//无比较器
        pq.add(2);
        pq.add(6);
        pq.add(3);

//        Integer poll = priorityQueue.poll();//获取并移除队列头部元素的方法。
//        Integer peek = priorityQueue.peek();//获取但不移除队列头部元素的方法。
//        System.out.println("priorityQueue.poll:"+poll);
//        System.out.println("priorityQueue.peek:"+peek);

        List<Integer> pqList = new ArrayList<>(pq);
        Collections.sort(pqList);//转换为List进行排序，如果需要按照自定义的优先级顺序输出元素，建议使用 poll() 方法逐个取出，或者将元素复制到列表中进行排序输出。
        System.out.println("Queue-pq:"+pq+"List-pqList:"+pqList);//输出结果：Queue-pq:[2, 6, 3]List-pqList:[2, 3, 6]
        for (Integer integer : pq) {
            System.out.println(integer);//输出结果2，6，3
        }
        while (!pq.isEmpty()) {
            int nextElement = pq.poll();//poll方法
            // 处理 nextElement，按照你的逻辑进行操作
            System.out.println(nextElement);//输出结果2，3，6
        }
    }

    /**
     * Set集合-HashSet和TreeSet介绍
     */
    private static void hashSetAndTreeSetAndLinkedHashSet() {
        //1-初始容量设定为5，如果元素个数大于当前容量与加载因子（默认的加载因子为 0.75）的乘积时将会自动进行扩容。
//        Set<String> tempSet = new HashSet<>(10);
//        tempSet.add("a2");
//        tempSet.add("a1");
//        tempSet.add("a4");
//        tempSet.add("a3");
//        tempSet.add("a5");
//        tempSet.add("a8");
//        tempSet.add("a6");
//        tempSet.add("a7");
//        tempSet.add("a9");
        //2-不重复性
//        Set<String> hashSet = new HashSet<>(tempSet);
//        Set<String> treeSet = new TreeSet<>(tempSet);

        //3-HashSet-基于哈希表（hashMap）实现-使用哈希函数来确定元素的存储位置
        //元素的存储顺序可能与插入顺序不同。
        //性能最高
        Set<String> hashSet = new HashSet<>(10);
        //4-TreeSet-基于红黑树（自平衡二叉搜索树）-保持元素的有序性
        //保证元素的自然顺序（或通过比较器自定义的顺序），元素按照升序排序。
        //性能偏低
        Set<String> treeSet = new TreeSet<>(new Comparator<String>() {//使用了比较器手动指定降序和升序
            @Override
            public int compare(String o1, String o2) {
                return String.CASE_INSENSITIVE_ORDER.compare(o2,o1);
            }
        });
        //5-LinkedHashSet-基于哈希表和双向链表实现-能够保持元素插入时的顺序
        //性能接近于HashSet
        Set<String> linkedHashSet = new LinkedHashSet<>();


        hashSet.add("a2");
        hashSet.add("a1");
        hashSet.add("a4");
        hashSet.add("a3");
        hashSet.add("a5");


        treeSet.add("a2");
        treeSet.add("a1");
        treeSet.add("a4");
        treeSet.add("a3");
        treeSet.add("a5");
        System.out.println("next:"+treeSet.iterator().next());

        linkedHashSet.add("a2");
        linkedHashSet.add("a1");
        linkedHashSet.add("a4");
        linkedHashSet.add("a3");
        linkedHashSet.add("a5");

        System.out.println("hashSet:"+hashSet);
        System.out.println("---------------------");
        System.out.println("treeSet"+treeSet);
        System.out.println("---------------------");
        System.out.println("linkedHashSet"+linkedHashSet);
        System.out.println("---------------------");
    }

    /**
     * List集合-ArrayList和LinkedList介绍
     */
    private static void arrayListAndLinkedList() {
    /*
    1-两者均不保证线程安全
    */
        List<String> arrayList = new ArrayList<>();
        List<String> linkedList = new LinkedList<>();
        /*
        2.1-ArrayList基于动态数组（索引）实现-在内存中是连续存储的，因此支持快速的随机访问（o(1)时间复杂度）
        2.2-当涉及到插入或者删除元素的时候，尤其是“中间或靠前的位置”会影响到很多的元素索引进行变动，效率较低，但是在末尾速度很快
        2.3-遍历快
        2.4-适用于需要频繁读取、按照索引访问元素的场景，如查找元素、通过索引获取元素等。
        */
        arrayList.add("a2");
        arrayList.add("a1");
        arrayList.add("a4");
        arrayList.add("a3");
        arrayList.add("a5");
        /*
        3.1-LinkedList基于双向链表实现(每个元素不仅要存储自身的内容，还要存储指向下一个元素的地址即指针)
        在内存中是随机存储的，节点之间通过指针连接，因此随机访问速度慢（o(n)时间复杂度）
        3.2-当涉及到插入或者删除元素的时候，只需要变更指定的方向即可，效率很高
        3.3-遍历较慢
        3.4-适用于需要频繁插入、删除操作的场景，尤其是在中间或靠前的位置。*/
        linkedList.add("a2");
        linkedList.add("a1");
        linkedList.add("a4");
        linkedList.add("a3");
        linkedList.add("a5");

        System.out.println("arrayList:"+arrayList);
        System.out.println("-------------------------");
        System.out.println("linkedList"+linkedList);
    }
}
